package com.frankle.mybatisplusgenerator.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Random;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 字符串工具类
 */
public class StringUtils {
	private final static Random random = new Random(System.currentTimeMillis());

	private final static char[] CHAR_LIST = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n',
			'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',
			'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7',
			'8', '9' };

	private final static char[] NUMBER_LIST = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };

	/**
	 * 功能描述：判断字符串是否为空白,包括null、""及"null"（固定参数）
	 * 
	 * @param str
	 * @return
	 */
	public static boolean isBlank(String str) {
		return str == null || str.trim().length() == 0 || str.equals("null") || "undefined".equalsIgnoreCase(str);
	}

	/**
	 * 功能描述：判断对象是否为空白（固定参数）
	 *
	 * @param o
	 * @return
	 */
	public static boolean isBlank(Object o) {
		return o == null || String.valueOf(o).trim().length() == 0 || "undefined".equals(o.toString());
	}

	/**
	 * 功能描述：是否为空白,包括null和""（可变参数）
	 *
	 * @param strs
	 * @return
	 */
	public static boolean isBlank(String... strs) {
		for (String str : strs) {
			if (isBlank(str)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 功能描述：是否不为空白,即!null且!""且!"null"
	 *
	 * @param str
	 * @return
	 */
	public static boolean isNotBlank(String str) {
		return !isBlank(str);
	}

	/**
	 * 功能描述：是否不为空白,即!null且!""且!"null"
	 *
	 * @param str
	 * @return
	 */
	public static boolean isNotBlank(Object str) {
		return !isBlank(str);
	}

	/**
	 * 功能描述：判断输入的字符串是否为纯汉字
	 *
	 * @param str 传入的字符窜
	 * @return 如果是纯汉字返回true,否则返回false
	 */
	public static boolean isChinese(String str) {
		if (isBlank(str)) {
			return false;
		}
		Pattern pattern = Pattern.compile("[\u0391-\uFFE5]+$");
		return pattern.matcher(str).matches();
	}

	/**
	 * 功能描述：判断是不是合法的手机号码
	 *
	 * @param str
	 * @return boolean
	 */
	public static boolean isMobile(String str) {
		if (isBlank(str)) {
			return false;
		}
		try {
			String regex = "^1[\\d]{10}$";
			Pattern pattern = Pattern.compile(regex);
			Matcher matcher = pattern.matcher(str);
			return matcher.matches();
		} catch (RuntimeException e) {
			return false;
		}
	}

	/**
	 * 电话号码验证
	 * 
	 * @param phone
	 * @return 验证通过返回true
	 */
	public static boolean isTelephone(String telephone) {
		Pattern p1 = null, p2 = null;
		Matcher m = null;
		boolean b = false;
		p1 = Pattern.compile("^[0][0-9]{2,3}-?[0-9]{5,10}$"); // 验证带区号的
		p2 = Pattern.compile("^[1-9]{1}[0-9]{5,8}$"); // 验证没有区号的
		if (telephone.length() > 9) {
			m = p1.matcher(telephone);
			b = m.matches();
		} else {
			m = p2.matcher(telephone);
			b = m.matches();
		}
		return b;
	}

	/**
	 * 功能描述：判断输入的字符串是否符合Email格式
	 *
	 * @param email 传入的字符串
	 * @return 是Email样式返回true,否则返回false
	 */
	public static boolean isEmail(String email) {
		if (email == null || email.length() < 1 || email.length() > 256) {
			return false;
		}
		Pattern pattern = Pattern.compile("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$");
		return pattern.matcher(email).matches();
	}

	/**
	 * 功能描述：校验身份证格式
	 *
	 * @param idCard
	 * @return 校验通过返回true，否则返回false
	 */
	public static boolean isIDCard(String idCard) {
		return Pattern.matches("(^\\d{18}$)|(^\\d{15}$)", idCard);
	}

	/**
	 * 功能描述：判断是否为浮点数，包括double和float
	 *
	 * @param str 传入的字符串
	 * @return 是浮点数返回true,否则返回false
	 */
	public static boolean isDouble(String str) {
		if (isBlank(str)) {
			return false;
		}
		Pattern pattern = Pattern.compile("^[-\\+]?\\d+\\.\\d+$");
		return pattern.matcher(str).matches();
	}

	/**
	 * 功能描述：判断是否为整数
	 *
	 * @param str 传入的字符串
	 * @return 是整数返回true,否则返回false
	 */
	public static boolean isInteger(String str) {
		if (isBlank(str)) {
			return false;
		}
		Pattern pattern = Pattern.compile("^[-\\+]?[\\d]+$");
		return pattern.matcher(str).matches();
	}

	/**
	 * 功能描述：判断是否为实数
	 *
	 * @param str 传入的字符串
	 * @return 是实数返回true,否则返回false
	 */
	public static boolean isNumber(String str) {
		if (isBlank(str)) {
			return false;
		}
		return isInteger(str) || isDouble(str);
	}

	/**
	 * 功能描述：判断是否为url请求地址
	 *
	 * @param str
	 * @return
	 */
	public static boolean isURL(String str) {
		if (isBlank(str)) {
			return false;
		}
		Pattern pattern = Pattern.compile("(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]");
		return pattern.matcher(str).matches();
	}

	/**
	 * 功能描述：获取一定长度的随机串(大小写字母及数字构成)
	 *
	 * @param length 需要生成的字符串长度
	 * @return
	 */
	public static String getRandomToken(int length) {
		StringBuilder token = new StringBuilder(length);
		for (int i = 0; i < length; i++) {
			char item = CHAR_LIST[random.nextInt(CHAR_LIST.length)];
			token.append(item);
		}
		return token.toString();
	}

	/**
	 * 功能描述：获取一定长度的验证码(纯数字构成)
	 *
	 * @param length 需要生成的字符串长度
	 * @return
	 */
	public static String getCAPTCHA(int length) {
		StringBuilder token = new StringBuilder(length);
		for (int i = 0; i < length; i++) {
			char item = NUMBER_LIST[random.nextInt(NUMBER_LIST.length)];
			token.append(item);
		}
		return token.toString();
	}

	/**
	 * 功能描述：获取UUID（已删除-符号）
	 *
	 * @return
	 */
	public static String getUUID() {
		return UUID.randomUUID().toString().replaceAll("-", "");
	}

	/**
	 * 功能描述：为空白字符串设置默认值
	 *
	 * @param str
	 * @param defaultStr 默认值
	 * @return
	 */
	public static String getOrDefault(String str, String defaultStr) {
		return isBlank(str) ? defaultStr : str;
	}

	/**
	 * 功能描述：去除字符串的半角、全角空格
	 *
	 * @param tmp 需要去除空格的字符串
	 * @return
	 */
	public static String removeBlankSpace(String tmp) {
		if (tmp == null) {
			return null;
		}
		return tmp.replaceAll("\\s*", "");
	}

	/**
	 * 功能描述：过滤特殊字符 包括：" ' < > & % _ # ？
	 *
	 * @param src
	 * @return
	 */
	public static String filterSpecialChar(String src) {
		if (src == null) {
			return "";
		}
		StringBuilder result = new StringBuilder((src = src.trim()).length());
		for (int pos = 0; pos < src.length(); pos++) {
			switch (src.charAt(pos)) {
			case '\"':
				result.append("&quot;");
				break;
			case '<':
				result.append("&lt;");
				break;
			case '>':
				result.append("&gt;");
				break;
			case '\'':
				result.append("&apos;");
				break;
			case '&':
				result.append("&amp;");
				break;
			case '%':
				result.append("&pc;");
				break;
			case '_':
				result.append("&ul;");
				break;
			case '#':
				result.append("&shap;");
				break;
			case '?':
				result.append("&ques;");
				break;
			default:
				result.append(src.charAt(pos));
				break;
			}
		}
		return result.toString();
	}

	/**
	 * 输入流转换成字符串
	 * @author Frankle
	 * @date 2020年5月5日
	 * @param is
	 * @return
	 */
	public static String convertString(InputStream is) {
		BufferedReader reader = null;
		StringBuilder sb = new StringBuilder();
		try {
			reader = new BufferedReader(new InputStreamReader(is, "utf-8"));
			String line = null;
			while ((line = reader.readLine()) != null) {
				sb.append(line);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (null != reader) {
					reader.close();
				}
			} catch (IOException e) {

			}
		}
		return sb.toString();
	}

	/**
	 * 往字符串左边补字符
	 * 
	 * @author heyufan
	 * @date 2018年11月20日 下午3:26:16
	 * @param str     原字符串
	 * @param padChar 填补的字符
	 * @param length  总长度
	 * @return
	 */
	public static String padLeft(String str, char padChar, int length) {
		if (str == null || length < 0) {
			throw new IllegalArgumentException("参数不正确");
		}
		StringBuffer sb = new StringBuffer();
		int padNums = 0;
		if (str.length() < length) {
			padNums = length - str.length();
			for (int i = 0; i < padNums; i++) {
				sb.append(padChar);
			}
		}
		sb.append(str);
		return sb.toString();
	}

	/**
	 * 往字符串右边补字符
	 * 
	 * @author heyufan
	 * @date 2018年11月20日 下午3:26:16
	 * @param str     原字符串
	 * @param padChar 填补的字符
	 * @param length  总长度
	 * @return
	 */
	public static String padRight(String str, char padChar, int length) {
		if (str == null || length < 0) {
			throw new IllegalArgumentException("参数不正确");
		}
		StringBuffer sb = new StringBuffer(str);
		int padNums = 0;
		if (str.length() < length) {
			padNums = length - str.length();
			for (int i = 0; i < padNums; i++) {
				sb.append(padChar);
			}
		}
		return sb.toString();
	}

	/**
	 * 检验是否是营业执照编号
	 * 
	 * @author heyufan
	 * @date 2019年1月12日 上午9:41:23
	 * @param str
	 * @return
	 */
	public static boolean isBussinessLicenseNumber(String license) {
		return isLicense15(license) || isLicense18(license);
	}

	/**
	 * 营业执照 统一社会信用代码（15位）
	 * 
	 * @param license
	 * @return
	 */
	public static boolean isLicense15(String license) {
		if (StringUtils.isBlank(license)) {
			return false;
		}
		if (license.length() != 15) {
			return false;
		}

		String businesslicensePrex14 = license.substring(0, 14);// 获取营业执照注册号前14位数字用来计算校验码
		String businesslicense15 = license.substring(14, license.length());// 获取营业执照号的校验码
		char[] chars = businesslicensePrex14.toCharArray();
		int[] ints = new int[chars.length];
		for (int i = 0; i < chars.length; i++) {
			ints[i] = Integer.parseInt(String.valueOf(chars[i]));
		}
		getCheckCode(ints);
		if (businesslicense15.equals(getCheckCode(ints) + "")) {// 比较 填写的营业执照注册号的校验码和计算的校验码是否一致
			return true;
		}
		return false;
	}

	/**
	 * 获取 营业执照注册号的校验码
	 * 
	 * @param ints
	 * @return
	 */
	private static int getCheckCode(int[] ints) {
		if (null != ints && ints.length > 1) {
			int ti = 0;
			int si = 0;// pi|11+ti
			int cj = 0;// （si||10==0？10：si||10）*2
			int pj = 10;// pj=cj|11==0?10:cj|11
			for (int i = 0; i < ints.length; i++) {
				ti = ints[i];
				pj = (cj % 11) == 0 ? 10 : (cj % 11);
				si = pj + ti;
				cj = (0 == si % 10 ? 10 : si % 10) * 2;
				if (i == ints.length - 1) {
					pj = (cj % 11) == 0 ? 10 : (cj % 11);
					return pj == 1 ? 1 : 11 - pj;
				}
			}
		} // end if
		return -1;
	}

	/**
	 * 营业执照 统一社会信用代码（18位）
	 * 
	 * @param license
	 * @return
	 */
	public static boolean isLicense18(String license) {
		if (StringUtils.isBlank(license)) {
			return false;
		}
		if (license.length() != 18) {
			return false;
		}

		String regex = "^([159Y]{1})([1239]{1})([0-9ABCDEFGHJKLMNPQRTUWXY]{6})([0-9ABCDEFGHJKLMNPQRTUWXY]{9})([0-90-9ABCDEFGHJKLMNPQRTUWXY])$";
		if (!license.matches(regex)) {
			return false;
		}
		String str = "0123456789ABCDEFGHJKLMNPQRTUWXY";
		int[] ws = { 1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28 };
		String[] codes = new String[2];
		codes[0] = license.substring(0, license.length() - 1);
		codes[1] = license.substring(license.length() - 1, license.length());
		int sum = 0;
		for (int i = 0; i < 17; i++) {
			sum += str.indexOf(codes[0].charAt(i)) * ws[i];
		}
		int c18 = 31 - (sum % 31);
		if (c18 == 31) {
			c18 = 'Y';
		} else if (c18 == 30) {
			c18 = '0';
		}
		if (str.charAt(c18) != codes[1].charAt(0)) {
			return false;
		}
		return true;
	}

	/**
	 * 判断是否是IP地址
	 * 
	 * @author heyufan
	 * @date 2019年4月30日 下午2:47:47
	 * @param ip
	 * @return
	 */
	public static boolean isIpAddress(String ip) {
		if (ip != null && !ip.isEmpty()) {
			// 定义正则表达式
			String regex = "^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\."
					+ "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\." + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
					+ "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)$";
			// 判断ip地址是否与正则表达式匹配
			if (ip.matches(regex)) {
				// 返回判断信息
				return true;
			} else {
				// 返回判断信息
				return false;
			}
		}
		return false;
	}
	
}
